#include "include/MatrixOperations.h"

MatrixOperations::MatrixOperations()
{

}
int MatrixOperations::Mats_multiply(float* input1, float* input2, float* output, int row, int n, int column)
{
    if (input1 != NULL && input2 != NULL && output != NULL && row > 0 && n > 0 && column > 0)
    {
        memset(output, 0, sizeof(float) * row * column);
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                output[i * column + j] = 0;
                for (int k = 0; k < n; k++)
                {
                    output[i * column + j] = output[i * column + j] + input1[i * n + k] * input2[(k) * (column)+j];
                }
            }
        }

        return 0;
    }
    else
        return -1;
}

int MatrixOperations::MatTrans(float* input, float* output, int input_row, int input_column)
{
    for (int i = 0; i < input_row; i++)
    {
        for (int j = 0; j < input_column; j++)
        {
            output[j * input_row + i] = input[input_column * i + j];
        }
    }
    return 0;
}

void MatrixOperations::MatAdd(float* input1, float* input2, float* output, int row, int column)
{
    for (int i = 0; i < (row * column); i++)
    {
        output[i] = input1[i] + input2[i];
    }
}

void MatrixOperations::MatDec(float* input1, float* input2, float* output, int row, int column)
{
    for (int i = 0; i < (row * column); i++)
    {
        output[i] = input1[i] - input2[i];
    }
}


void MatrixOperations::Matinv(float* source, float* dest, int order)
{
    if (order == 2)
    {
        float det = source[0] * source[3] - source[1] * source[2];
        dest[0] = source[3];
        dest[3] = source[0];
        dest[1] = (-1.0f) * source[1];
        dest[2] = (-1.0f) * source[2];

        for (int i = 0; i < (order * order); i++)
        {
            dest[i] = dest[i] / det;
        }
    }
    else if (order == 3)
    {
        float det = source[0 * order + 0] * source[1 * order + 1] * source[2 * order + 2]
                    + source[0 * order + 1] * source[1 * order + 2] * source[2 * order + 0]
                    + source[0 * order + 2] * source[1 * order + 0] * source[2 * order + 1]
                    - source[0 * order + 2] * source[1 * order + 1] * source[2 * order + 0]
                    - source[0 * order + 0] * source[1 * order + 2] * source[2 * order + 1]
                    - source[0 * order + 1] * source[1 * order + 0] * source[2 * order + 2];
        dest[0 * order + 0] = source[1 * order + 1] * source[2 * order + 2] - source[1 * order + 2] * source[2 * order + 1];
        dest[0 * order + 1] = -(source[0 * order + 1] * source[2 * order + 2] - source[0 * order + 2] * source[2 * order + 1]);
        dest[0 * order + 2] = source[0 * order + 1] * source[1 * order + 2] - source[0 * order + 2] * source[1 * order + 1];

        dest[1 * order + 0] = -(source[1 * order + 0] * source[2 * order + 2] - source[1 * order + 2] * source[2 * order + 0]);
        dest[1 * order + 1] = source[0 * order + 0] * source[2 * order + 2] - source[0 * order + 2] * source[2 * order + 0];
        dest[1 * order + 2] = -(source[0 * order + 0] * source[1 * order + 2] - source[0 * order + 2] * source[1 * order + 0]);

        dest[2 * order + 0] = source[1 * order + 0] * source[2 * order + 1] - source[1 * order + 1] * source[2 * order + 0];
        dest[2 * order + 1] = -(source[0 * order + 0] * source[2 * order + 1] - source[0 * order + 1] * source[2 * order + 0]);
        dest[2 * order + 2] = source[0 * order + 0] * source[1 * order + 1] - source[0 * order + 1] * source[1 * order + 0];

        for (int i = 0; i < (order * order); i++)
        {
            dest[i] = dest[i] / det;
        }
    }
    else
        std::cout << "Please input the third-order matrix!" << std::endl;

}

void MatrixOperations::MatDiv(int*** input1, int*** input2, int*** output, int first, int second, int third) {
    for (int i = 0; i < first; i++) {
        for (int j = 0; j < second; j++) {
            for (int k = 0; k < third; k++) {
                if (input2[i][j][k] == 0)
                    input2[i][j][k] = 1;
                output[i][j][k] = input1[i][j][k] / input2[i][j][k];
            }
        }
    }
}
